﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using PloobsEngine.Modelo;
using PloobsEngine.Material;
using PloobsEngine.Physics;
using PloobsEngine.Utils;

namespace PloobsEngine.SceneControl
{    

    public struct LodDesc
    {
        public IModelo Modelo;
        public IMaterial Material;
        public float Distance; 
    }

    /// <summary>
    /// Lod Object
    /// </summary>
    public class LodObject : SimpleObject
    {
        public LodObject(IMaterial mat, IPhysicObject phy, IModelo model)
            : base(mat, phy, model)
        {
            this.modeloActive = model;
            this.materialActive = mat;
            timePassed = new TimePassed(5);
        }

        /// <summary>
        /// Lod Object
        /// </summary>
        /// <param name="mat"></param>
        /// <param name="phy"></param>
        /// <param name="model"></param>
        /// <param name="intervalToUpdate">Internval to see if change of the lod is needed</param>
        public LodObject(IMaterial mat, IPhysicObject phy, IModelo model,float intervalToUpdate)
            : base(mat, phy, model)
        {
            this.modeloActive = model;
            this.materialActive = mat;
            timePassed = new TimePassed(intervalToUpdate);
        }

        private SortedDictionary<float, LodDesc> lods = new SortedDictionary<float, LodDesc>();
        IMaterial materialActive = null;
        IModelo modeloActive = null;
        TimePassed timePassed;

        /// <summary>
        /// Add one Lod Model
        /// </summary>
        /// <param name="modelo">Model, can be null to use the current</param>
        /// <param name="mat">Material, can be null to use the current</param>
        /// <param name="distance">maximum distance to be active</param>
        public void AddLod(IModelo modelo, IMaterial mat, float distance)
        {
            LodDesc ld = new LodDesc();            
            ld.Distance = distance;
            if (modelo == null)
                ld.Modelo = Modelo;
            else
                ld.Modelo = modelo;
            if (mat == null)
                ld.Material = Material;
            else
                ld.Material = mat;

            lods.Add(ld.Distance, ld);
        }

        /// <summary>
        /// Remove a lod
        /// </summary>
        /// <param name="distance">the maximum distance passed when lod was created</param>
        public void RemoveLod(float distance)
        {
            lods.Remove(distance);
        }

        public LodDesc GetLodDescription(float distance)
        {
            return lods[distance];            
        }

        public float[] GetLodsActivateds()
        {
            return lods.Keys.ToArray();
        }


        bool canChangeLodNow = true;

        /// <summary>
        /// Can Change Lod in the next chance ?
        /// </summary>
        public bool CanChangeLodNow
        {
            get { return canChangeLodNow; }
            set { canChangeLodNow = value; }
        }

        public override void UpdateObject(Microsoft.Xna.Framework.GameTime gt, PloobsEngine.Cameras.ICamera cam, IList<PloobsEngine.Light.ILight> luzes)
        {
            base.UpdateObject(gt, cam, luzes);

            if(canChangeLodNow)
            {
                if (timePassed.hasPassed())
                {
                    float distanceCurrent = 0;
                    foreach (var item in lods.Keys)
	                {   
                        LodDesc l = lods[item];
                        if (CameraDistance < l.Distance && CameraDistance > distanceCurrent)
                        {
                            Material = l.Material;
                            Modelo = l.Modelo;
                            break;
                        }
                        else
                        {
                            distanceCurrent = l.Distance;
                        }
                    }
                }                            
            	 
			 }
            
        }

        public override PloobsEngine.Material.IMaterial Material
        {
            get
            {
                return base.Material;
            }
            set
            {
                base.Material = value;
            }
        }

        public override PloobsEngine.Modelo.IModelo Modelo
        {
            get
            {
                return base.Modelo;
            }
            set
            {
                base.Modelo = value;
            }
        }
    }
}
